/*
 * Copyright (C) 2015-2016  Nicola Spanti (RyDroid) <dev@nicola-spanti.info>
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */


#include "PlanetWars2dRT-SDL2/specific/view/draw_vector_game.h"
#include "PlanetWars2dRT-SDL2/specific/view/draw_vector_universe.h"
#include "PlanetWars2dRT-SDL2/utils/SDL.h"
#include <SDL2_gfxPrimitives.h>
#include "PlanetWars2dRT-core/specific/view/draw_generic_game.h"
#include "PlanetWars2dRT-core/specific/controller/game_end.h"


EXTERN_C_BEGIN


struct SDL_generic_draw_element_extra_data
{
  SDL_Renderer* renderer;
  const game_t* game;
  FILE*         error_stream;
};
typedef struct SDL_generic_draw_element_extra_data SDL_generic_draw_element_extra_data;

typedef SDL_generic_draw_element_extra_data SDL_generic_draw_planet_extra_data;
typedef SDL_generic_draw_element_extra_data SDL_generic_draw_ship_extra_data;


bool
SDL_draw_vector_planet(SDL_Renderer*   renderer,
		       const planet_t* a_planet,
		       const game_t*   a_game,
		       FILE*           error_stream)
{
  color_rgb color;
  if(a_planet->player_index == NULL_PLAYER_INDEX)
    {
      color.red   = PLAYER_NEUTRAL_COLOR_RED_PLANET;
      color.green = PLAYER_NEUTRAL_COLOR_GREEN_PLANET;
      color.blue  = PLAYER_NEUTRAL_COLOR_BLUE_PLANET;
    }
  else
    {
      const player_t* player_i =
	game_get_const_player_no_check(a_game,
				       a_planet->player_index);
      color = player_get_color_rgb_planet(player_i);
    }
  
  return SDL_draw_vector_planet_with_defined_color(renderer,
						   a_planet,
						   color.red,
						   color.green,
						   color.blue,
						   255,
						   error_stream);
}

bool
SDL_generic_draw_vector_planet(const planet_t* a_planet,
			       const void*     extra_data)
{
  SDL_generic_draw_ship_extra_data* data =
    (SDL_generic_draw_ship_extra_data*) extra_data;
  return SDL_draw_vector_planet(data->renderer, a_planet, data->game,
				data->error_stream);
}

bool
SDL_draw_vector_planets_of_game(SDL_Renderer* renderer,
				const game_t* a_game,
				FILE*         error_stream,
				bool          stop_on_error)
{
  SDL_generic_draw_ship_extra_data data;
  data.renderer     = renderer;
  data.game         = a_game;
  data.error_stream = error_stream;
  return generic_draw_planets_of_game(a_game,
				      SDL_generic_draw_vector_planet,
				      &data,
				      stop_on_error);
}

bool
SDL_draw_vector_ship(SDL_Renderer* renderer,
		     const ship_t* a_ship,
		     const game_t* a_game,
		     FILE*         error_stream)
{
  color_rgb color;
  if(a_ship->player_index == NULL_PLAYER_INDEX)
    {
      color.red   = PLAYER_NEUTRAL_COLOR_RED_SHIP;
      color.green = PLAYER_NEUTRAL_COLOR_GREEN_SHIP;
      color.blue  = PLAYER_NEUTRAL_COLOR_BLUE_SHIP;
    }
  else
    {
      const player_t* player_i =
	game_get_const_player_no_check(a_game,
				       a_ship->player_index);
      color = player_get_color_rgb_ship(player_i);
    }
  
  return SDL_draw_vector_ship_with_defined_color(renderer,
						 a_ship,
						 color.red,
						 color.green,
						 color.blue,
						 255,
						 error_stream);
}

bool
SDL_generic_draw_vector_ship(const ship_t* a_ship,
			     const void*   extra_data)
{
  SDL_generic_draw_ship_extra_data* data =
    (SDL_generic_draw_ship_extra_data*) extra_data;
  return SDL_draw_vector_ship(data->renderer, a_ship, data->game,
			      data->error_stream);
}

bool
SDL_draw_vector_ships_of_game(SDL_Renderer* renderer,
			      const game_t* a_game,
			      FILE*         error_stream,
			      bool          stop_on_error)
{
  SDL_generic_draw_ship_extra_data data;
  data.renderer     = renderer;
  data.game         = a_game;
  data.error_stream = error_stream;
  return generic_draw_ships_of_game(a_game,
				    SDL_generic_draw_vector_ship,
				    &data,
				    stop_on_error);
}

const struct generic_draw_game_functions SDL_GENERIC_DRAW_GAME_FUNCTIONS =
  {
    .planet = SDL_generic_draw_vector_planet,
    .ship   = SDL_generic_draw_vector_ship
  };

bool
SDL_draw_vector_game(SDL_Renderer* renderer,
		     const game_t* a_game,
		     FILE*         error_stream,
		     bool          stop_on_error)
{
  SDL_generic_draw_element_extra_data element_data;
  element_data.renderer     = renderer;
  element_data.game         = a_game;
  element_data.error_stream = error_stream;
  struct generic_draw_game_extra_data extra_data;
  extra_data.planets     = &element_data;
  extra_data.ships       = &element_data;
  extra_data.black_holes = &element_data;
  extra_data.wormholes   = &element_data;
  extra_data.supernovas  = &element_data;
  
  return generic_draw_game(a_game,
			   &SDL_GENERIC_DRAW_GAME_FUNCTIONS,
			   &extra_data,
			   stop_on_error);
}

bool
SDL_draw_vector_game_end_message(SDL_Renderer* renderer,
				 const game_t* a_game,
				 FILE*         error_stream)
{
  const player_t* a_player = game_get_winner(a_game);
  if(a_player == NULL)
    {
      return false;
    }
  
  char* end_game_msg = game_end_message_winner_with_player(a_player);
  if(end_game_msg == NULL)
    {
      return false;
    }
  bool success = stringRGBA(renderer, 0, 0, end_game_msg,
			    255, 255, 255, 255) == 0;
  free(end_game_msg);
  
  if(!success)
    {
      fprintf(error_stream,
	      "The message of the end of the game was not rendered!\n");
      SDL_print_error();
    }
  return success;
}

bool
SDL_draw_vector_game_end(SDL_Renderer* renderer,
			 const game_t* a_game,
			 FILE*         error_stream)
{
  return
    SDL_draw_vector_game            (renderer, a_game, error_stream, true) &&
    SDL_draw_vector_game_end_message(renderer, a_game, error_stream);
}


EXTERN_C_END
